//-------------------------------------------------------------------------
/**
   File:   Commandline.h

   Descr.: simple commandline parsing wrapper

   Author: Stefan Leihkauf
   Date:   23.03.2014
*/
//-------------------------------------------------------------------------
#ifndef _COMMANDLINE_H
#define _COMMANDLINE_H
#include "common/types/typedef.h"

namespace cb {

/* 
    Here is what I think how a commandline should look like:
    - the first string at index zero is the command itself
    - following are options, switches and arguments
        - switches are introduced by a leading '-' or '--' 
        - options are introduced as like switches followd by '=' and one or more value strings
          delimited by '|'
        - arguments are standalone strings and seperated by whitespaces
    - the order of switches, options and argument is not relevant

    <command> -<switch> --<switch> -<option>=<value> --<option>=<value> <argument0> <argument1> ... 
*/
class Commandline
{
public:    
    // commandline options
    struct Option
    {
        StdString Key;
        StringList Values;

        Option() 
        { /*empty*/ }

        Option(const StdString& key) :
            Key(key)
        { /*empty*/ }

        Option(const StdString& key, const StringList& values) :
            Key(key), Values(values)
        { /*empty*/ }

        // check if empty
        bool IsEmpty() const
        { return ((*this) == Commandline::Option::Empty()); }

        // equality
        bool operator == (const Commandline::Option& other) const
        { return ((Key == other.Key) && (Values == other.Values)); }

        // empty option
        static Commandline::Option Empty()
        { return Option(); }
    };

    // commandline options
    typedef std::vector<Option> OptionList;

    // commandline arguments
    typedef StringList ArgumentList;

public:
    // constructor
    Commandline();
    Commandline(int numArgs, const TCHAR** ppArgv);
    
    // destructor
    ~Commandline();

    // set commandline
    void Set(int numArgs, const TCHAR** ppArgv);
    void Set(const StringList& commandLine);

    // get the command
    StdString Command() const;

    // get options
    OptionList Options() const;

    // get arguments
    ArgumentList Arguments() const; 

private:
    void Parse(const StringList& cmdLine);
    bool IsSwitch(const StdString& str) const;
    bool IsOption(const StdString& str) const;

    void AddSwitch(const StdString& str);
    void AddOption(const StdString& str);

    StdString RemoveOptionDelimiter(const StdString& str) const;

    StdString _command;
    OptionList _options;
    ArgumentList _arguments;
};


} // namespace
#endif //!defined _COMMANDLINE_H